﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using THO7_Team8.Filters;

namespace THO7_Team8
{
	public partial class ExtendedForm : Form
	{
		Bitmap InputImage;
		Bitmap ResultImage;
		String LastOperationName;
		ConsoleViewerDialog statusconsole;
		Stopwatch stopWatch;
		List<VisionAlgorithm> AlgorithmList = new List<VisionAlgorithm>();
		List<ToolStripMenuItem> ImageRelatedMenuItems = new List<ToolStripMenuItem>();

		public ExtendedForm()
		{
			InitializeComponent();
			statusconsole = new ConsoleViewerDialog();
			//statusconsole.MdiParent = this;
			//AlgorithmList.Add(new FlipAlgorithm("Flip"));
			//AlgorithmList.Add(new RotateAlgorithm("Rotate"));
			//AlgorithmList.Add(new InvertAlgorithm("Invert"));
			//AlgorithmList.Add(new InvertAlgorithm_4bytes("Invert (4 bytes)"));
			//AlgorithmList.Add(new InvertAlgorithm_16bytes("Invert (16 bytes)"));
			//AlgorithmList.Add(new BlackOutAlgorithm("Black Out"));
			//AlgorithmList.Add(new Greyscale("Greyscale"));
			//AlgorithmList.Add(new UnsafeBlackout("Unsafe Black Out"));
			AlgorithmList.Add(new MedianFilter("MedianFilter"));
			//AlgorithmList.Add(new FastMedianFilter("Fast MedianFilter"));
			AlgorithmList.Add(new SaltAndPepperNoise("Salt and Pepper Noise"));
			AlgorithmList.Add(new WeightedColorNoise("Weighted Color Noise"));
			AlgorithmList.Add(new MagicAlgorithm("The magic kernel"));
			//AlgorithmList.Add(new CostellaSuperior("Costella Gradient Superior"));
			AlgorithmList.Add(new GaussianBlur("Gaussian Blur"));
			//AlgorithmList.Add(new DynamicThreshold("Dynamic Threshold"));
			//AlgorithmList.Add(new PlateDetector("Plate Detector"));
			//AlgorithmList.Add(new KMeansAlgorithm("KMeans"));
			//AlgorithmList.Add(new SimpleColorDetect("Simple Color Detect"));
			//AlgorithmList.Add(new NumberPlateLetterDetection("LineDetection"));
			//AlgorithmList.Add(new NormalLetterDetection("Normal Letter Detection"));
			// AlgorithmList.Add(new CropCharacter("CropToCharSize"));
			AlgorithmList.Add(new SimpleColorDetectMonogrome("Simple Color Detect"));
			AlgorithmList.Add(new CropLicenseplate("Crop License Plate"));
			AlgorithmList.Add(new CropEdges("Crop Edges"));
			AlgorithmList.Add(new RotateLicensePlate("Rotate License Plate"));
			AlgorithmList.Add(new MakeMonochrome("Make Monochrome"));
			AlgorithmList.Add(new LicensePlateBlobDetection("License Plate Blob Detection"));
			//AlgorithmList.Add(new imYellow("Make Yellow"));
			AlgorithmList.Add(new Batch("Locate License Plate"));
			//AlgorithmList.Add(new CropLicenseplateColoured("Crop License Plate Colored"));

			//AlgorithmList.Add(new LightingAlgorithm("lightning"));

			AlgorithmList.Add(new OCRTest("OCR Test"));

			//Insert new Algorithms here
			/*          ^
			*          /|\
			*           |
			*/

			foreach(VisionAlgorithm vA in AlgorithmList)
			{
				filterToolStripMenuItem.DropDownItems.Add(vA.Name);
			}

			ImageRelatedMenuItems.Add(closeImageToolStripMenuItem);
			ImageRelatedMenuItems.Add(saveImageAsToolStripMenuItem);
			ImageRelatedMenuItems.Add(filterToolStripMenuItem);
		}

		public VisionAlgorithm getVisionAlgorithmByName(String s)
		{
			foreach(VisionAlgorithm va in AlgorithmList)
			{
				if(va.Name == s)
				{
					return va;
				}
			}
			throw new NotImplementedException();
		}

		private void openImage(object sender, EventArgs e)
		{
			OpenFileDialog oFD = new OpenFileDialog();
			oFD.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);
			oFD.Filter = "Image Files(*.BMP;*.JPG;*.JPEG;*.PNG;)|*.BMP;*.JPG;*.JPEG;*.PNG;";
			oFD.FilterIndex = 1;
			oFD.RestoreDirectory = true;
			if(oFD.ShowDialog() == DialogResult.OK)
			{
				String CurrentFileName = Path.GetFullPath(oFD.FileName);
				InputImage = new Bitmap(CurrentFileName);
				ImageEditWindow ipf1 = new ImageEditWindow(InputImage);
				ipf1.MdiParent = this;
				ipf1.Show();
				//InputPictureBox.Image = InputImage;
				//AlgoButton.Enabled = true;
				foreach(ToolStripMenuItem tSi in ImageRelatedMenuItems)
				{
					tSi.Enabled = true;
				}
			}
			else
			{
				//AlgoButton.Enabled = false;
			}
		}

		public void setStatusBarText(String text)
		{
			statusconsole.addLine(text);
			toolStripStatusLabel1.Text = text;
		}

		private void backgroundAlgorithmWorker_DoWork(object sender, DoWorkEventArgs e)
		{
			System.ComponentModel.BackgroundWorker worker;
			worker = (System.ComponentModel.BackgroundWorker) sender;
			List<object> argList = (List<object>) e.Argument;
			VisionAlgorithm visAlg = (VisionAlgorithm) argList.ElementAt(0);
			Bitmap InputImage = (Bitmap) argList.ElementAt(1);
			ImageEditWindow iew = (ImageEditWindow) argList.ElementAt(2);
			ResultImage = visAlg.DoAlgorithm(InputImage);
			LastOperationName = visAlg.Name;
			//            OutputPictureBox.Image = visAlg.DoAlgorithm(InputImage);
			stopWatch.Stop();
		}

		private void filterToolStripMenuItem_DropDownItemClicked(object sender, ToolStripItemClickedEventArgs e)
		{
			startAlgThread(filterToolStripMenuItem.DropDownItems.IndexOf(e.ClickedItem), (ImageEditWindow) this.ActiveMdiChild);
		}

		private void exitToolStripMenuItem_Click(object sender, EventArgs e)
		{
			Application.Exit();
		}

		private void startAlgThread(int clickedItem, ImageEditWindow iew)
		{
			List<object> argList = new List<object>();
			if(((VisionAlgorithm) AlgorithmList.ElementAt(clickedItem)).hasConfiguration)
			{
				VisionAlgorithm selectedAlgorithm = AlgorithmList.ElementAt(clickedItem);
				ConfigForm selectedAlgoConfig = (ConfigForm) selectedAlgorithm.configuration;
				selectedAlgoConfig.ShowDialog();
				selectedAlgorithm._configValue = selectedAlgoConfig._configValue;
				selectedAlgoConfig.Hide();
			}
			else
			{
				Console.WriteLine("No Configuration for " + ((VisionAlgorithm) AlgorithmList.ElementAt(clickedItem)).Name);
				Console.WriteLine("Just trying shit: " + ((VisionAlgorithm) getVisionAlgorithmByName("MedianFilter")).ConfigValue);
			}
			argList.Add(AlgorithmList.ElementAt(clickedItem));
			argList.Add(iew.getCurrent());
			argList.Add(iew);
			stopWatch = new Stopwatch();
			//EnableAllInputs(false);
			setStatusBarText("Starting operation " + ((VisionAlgorithm) AlgorithmList.ElementAt(clickedItem)).Name + "...");
			stopWatch.Start();
			foreach(ToolStripMenuItem tSi in ImageRelatedMenuItems)
			{
				tSi.Enabled = false;
			}
			backgroundAlgorithmWorker.RunWorkerAsync(argList);
		}

		private void closeImageToolStripMenuItem_Click(object sender, EventArgs e)
		{
			this.ActiveMdiChild.Close();
			if(this.MdiChildren.Length == 0)
			{
				foreach(ToolStripMenuItem tSi in ImageRelatedMenuItems)
				{
					tSi.Enabled = false;
				}
			}
		}

		private void backgroundAlgorithmWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
		{
			stopWatch.Stop();
			ImageEditWindow temp = (ImageEditWindow) this.ActiveMdiChild;
			temp.addEditedPicture(ResultImage, LastOperationName);
			foreach(ToolStripMenuItem tSi in ImageRelatedMenuItems)
			{
				tSi.Enabled = true;
			}
			setStatusBarText("Last operation (" + LastOperationName + ") took " + stopWatch.ElapsedMilliseconds + "ms");
		}

		private void toolStripStatusLabel1_Click(object sender, EventArgs e)
		{
			statusconsole.ShowDialog();
		}

		private static ImageCodecInfo GetEncoderInfo(String mimeType)
		{
			int j;
			ImageCodecInfo[] encoders;
			encoders = ImageCodecInfo.GetImageEncoders();
			for(j = 0; j < encoders.Length; ++j)
			{
				if(encoders[j].MimeType == mimeType)
					return encoders[j];
			}
			return null;
		}

		private void saveImageAsToolStripMenuItem_Click(object sender, EventArgs e)
		{
			SaveFileDialog saveFileDialog1 = new SaveFileDialog();
			saveFileDialog1.Filter = "Jpeg Image|*.jpg|Bitmap Image|*.bmp|PNG Image|*.png";
			saveFileDialog1.Title = "Save an Image File";
			saveFileDialog1.ShowDialog();

			// If the file name is not an empty string open it for saving.
			if(saveFileDialog1.FileName != "")
			{
				// Saves the Image via a FileStream created by the OpenFile method.
				System.IO.FileStream fs =
                   (System.IO.FileStream) saveFileDialog1.OpenFile();
				ImageEditWindow activeWindow = (ImageEditWindow) ActiveMdiChild;
				activeWindow.getCurrent();
				// Saves the Image in the appropriate ImageFormat based upon the
				// File type selected in the dialog box.
				// NOTE that the FilterIndex property is one-based.
				switch(saveFileDialog1.FilterIndex)
				{
					case 1:
						ImageCodecInfo myImageCodecInfo;
						System.Drawing.Imaging.Encoder myEncoder;
						EncoderParameter myEncoderParameter;
						EncoderParameters myEncoderParameters;
						// Get an ImageCodecInfo object that represents the JPEG codec.
						myImageCodecInfo = GetEncoderInfo("image/jpeg");
						// Create an Encoder object based on the GUID

						// for the Quality parameter category.
						myEncoder = System.Drawing.Imaging.Encoder.Quality;
						myEncoderParameters = new EncoderParameters(1);

						// Save the bitmap as a JPEG file with quality level 25.
						myEncoderParameter = new EncoderParameter(myEncoder, 80L);
						myEncoderParameters.Param[0] = myEncoderParameter;
						activeWindow.getCurrent().Save(fs, myImageCodecInfo, myEncoderParameters);
						break;

					case 2:
						activeWindow.getCurrent().Save(fs,
						   System.Drawing.Imaging.ImageFormat.Bmp);
						break;

					case 3:
						activeWindow.getCurrent().Save(fs,
						   System.Drawing.Imaging.ImageFormat.Png);
						break;
				}

				fs.Close();
			}
		}

		private void ExtendedForm_DragDrop(object sender, DragEventArgs e)
		{
			if(e.Data.GetDataPresent(DataFormats.FileDrop))
			{
				string[] files = (string[]) e.Data.GetData(
					DataFormats.FileDrop);
				foreach(string file in files)
				{
					FileInfo fileInfo = new FileInfo(file);
					if(fileInfo.Extension.ToLower() == ".jpg" || fileInfo.Extension.ToLower() == ".bmp" || fileInfo.Extension.ToLower() == ".png")
					{
						Console.WriteLine("Nieuwe file: " + file);
						InputImage = new Bitmap(file);
						ImageEditWindow ipf1 = new ImageEditWindow(InputImage);
						ipf1.MdiParent = this;
						ipf1.Show();
						foreach(ToolStripMenuItem tSi in ImageRelatedMenuItems)
						{
							tSi.Enabled = true;
						}
						setStatusBarText("Opened a new image from Drag & Drop: " + file);
					}
				}
			}
		}

		private void ExtendedForm_DragEnter(object sender, DragEventArgs e)
		{
			if(e.Data.GetDataPresent(DataFormats.FileDrop))
				e.Effect = DragDropEffects.Move;
			else
				e.Effect = DragDropEffects.None;
		}

		private void testSetDialogToolStripMenuItem_Click(object sender, EventArgs e)
		{
			THO7_Team8.Dialogs.OcrTestsetDialog otd = new Dialogs.OcrTestsetDialog();
			otd.MdiParent = this;
			otd.Show();
		}

		private void matchMakerToolStripMenuItem_Click(object sender, EventArgs e)
		{
			THO7_Team8.Dialogs.MatchMaker mm = new Dialogs.MatchMaker();
			mm.MdiParent = this;
			mm.Show();
		}

		private void batchProcessingToolStripMenuItem_Click(object sender, EventArgs e)
		{
			THO7_Team8.Dialogs.BatchDialog bd = new Dialogs.BatchDialog(AlgorithmList);

			bd.MdiParent = this;
			bd.Show();
		}
	}
}